#pragma once

#include <iostream>
#include <queue>
#include <vector>
#include <pthread.h>
#include <functional>
#include "Log.hpp"
#include "Thread.hpp"
#include "LockGuard.hpp"

static const int defaultnum = 5;//线程池中默认线程个数

class ThreadData
{
public:
      ThreadData(const std::string &name):threadname(name)
      {

      }

      ~ThreadData()
      {
    
      }
public:
      std::string threadname;
};

template<class T>
class ThreadPool
{
public:
    ThreadPool(int thread_num = defaultnum):_thread_num(thread_num)
    {
      pthread_mutex_init(&_mutex, nullptr);
      pthread_cond_init(&_cond, nullptr);

      //构建指定个数的线程
      for(int i = 0; i < _thread_num; i++)
      {
            //待优化，创建一个线程默认要传入名字，要执行的函数，和数据
            std::string threadname = "thread-";            
            threadname += std::to_string(i+1);
            ThreadData td(threadname);

            //绑定执行线程池给他提供的方法Threadrun
            // Thread<ThreadData> t(threadname, std::bind(&ThreadPool<T>::ThreadRun, this, std::placeholders::_1), td);
            // _threads.push_back(t);

            _threads.emplace_back(threadname, \
                       std::bind(&ThreadPool<T>::ThreadRun, this, std::placeholders::_1), td);

            lg.LogMessage(Info, "%s is created...\n", threadname.c_str());
      }
    }
   
    
    bool Start()//启动线程池
    {
      //启动
      for(auto &thread : _threads)
      {
            thread.Start();//调用线程启动的方法
            lg.LogMessage(Info, "%s if running ...\n", thread.ThreadName().c_str());

      }
      return true;
      

    }

    void ThreadWait(const ThreadData &td)
    {
      lg.LogMessage(Debug, "no task, %s is sleeping...\n", td.threadname.c_str());
      pthread_cond_wait(&_cond, &_mutex);
    }

    void ThreadWakeup()
    {
      
      pthread_cond_signal(&_cond);
    }

    void ThreadRun(ThreadData &td)//线程要执行的方法
    {
      while(true)
      {
            // std::cout << "thread is running ..." << std::endl;
            // sleep(1);

            //取任务要加锁
            T t;
            {
                  LockGuard lockguard(&_mutex);
                  while(_q.empty())
                  {
                        ThreadWait(td);
                        lg.LogMessage(Debug, "thread %s is wakeup\n", td.threadname.c_str());
                  }
                  t = _q.front();
                  _q.pop();
            } 
            //处理任务
            t();   
            //std::cout << "handler done..." << t.PrintResult() << std::endl;
            lg.LogMessage(Debug, "%s handler task %s done, result is : %s\n", \
                    td.threadname.c_str(), t.PrintTask().c_str(), t.PrintResult().c_str());
      }


    }

    void Push(const T &in)//不会改任务所以加const
    {
      lg.LogMessage(Debug, "other thread push a task, task is : %s\n", in.PrintTask().c_str());
      LockGuard lockguard(&_mutex);
      _q.push(in);
      ThreadWakeup();
      

    }

     ~ThreadPool()
    {
      pthread_mutex_destroy(&_mutex);
      pthread_cond_destroy(&_cond);

    }

    //for debug
    void Wait()
    {
      for(auto &thread : _threads)
      {
            thread.Join();
      }
    }


private:
    std::queue<T> _q;//任务队列
    std::vector<Thread<ThreadData>> _threads;//一批线程
    int _thread_num;//线程池中有多少个线程
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;   

};